package com.jiuzhe.commercial.ui.components;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Scroller;

public class EQGirdListViewBase extends ListView implements OnScrollListener, OnGestureListener {
    private static final int   INVALID_COLUMN  = -1;
    private static final int   DIRECTION_NONE  = 0;
    private static final int   DIRECTION_LEFT  = 1;
    private static final int   DIRECTION_RIGHT = 2;
    /**
     * The velocity at which a fling gesture will cause us to snap to the next screen
     */
    private static final int   SNAP_VELOCITY   = 500;
    private Paint              mPaint;
    private int                mCurrentColumn;
    private int                mNextColumn     = INVALID_COLUMN;
    private Scroller           mScroller;
    private VelocityTracker    mVelocityTracker;
    private float              mLastMotionX;
    private float              mLastMotionDownX;
    private float              mLastMotionDownY;
    private boolean            mIsDragging;
    private boolean			   isResetFooterView = false;
    private int                mLastScrollX;
    private boolean            mLocked;
    private int                mTouchSlop;
    protected EQGirdScrollableListItem listHeader;
    protected TableBaseObj.EQTableOnListener eQTableOnListener;
    protected String reportLayerName;

    boolean enableFastScroll;
    int popTipInterval;
    int popTipItemCount;
    int currentFirstItem;
    public int mFirstVisibleItem = 0;
    int beforeScrollFirstPosition;
    float beforeScrollY;
    static final int POP_UNSET = 0;
    static final int POP_ENABLE = 1;
    static final int POP_DISABLE = 2;
    int popState;

    private int mDirection;

    // 上拉加载更多功能
    private float mLastY = -1; // save event y
    private EQCustomListViewFooterLoadMore mFooterView;
    private EQCustomListViewListener mListViewListener;
    private boolean mEnablePullLoad;
    private boolean mPullLoading;
    private boolean mIsFooterReady = false;
    private boolean isActionUp = false;
    private int mScrollBack;
    private int mTotalItemCount;
    public int scrollState = -1;
    public final static int GOTO_SELECT = 0;
    private final static int SCROLLBACK_HEADER = 0;
    private final static int SCROLLBACK_FOOTER = 1;
    private final static int SCROLL_DURATION = 200;
    private final static int PULL_LOAD_MORE_DELTA = 60;
    private final static float OFFSET_RADIO_FOOTER = 1.0f;
    private final static int FOOTER_HEIGHT = 120;
    private DataChangedListener dataChangedListener;

    public EQGirdListViewBase(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initAttrs(context, attrs);
        onFinishInflate();
    }

    public EQGirdListViewBase(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttrs(context, attrs);
        onFinishInflate();
    }

    public EQGirdListViewBase(Context context) {
        super(context);
        initAttrs(context, null);
        onFinishInflate();
    }

    private void initAttrs(Context context, AttributeSet attrs) {
        if (context != null && attrs != null) {
            this.enableFastScroll = false;
            this.popTipInterval = 1;
            this.popTipItemCount = 2;
        }
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mScroller = new Scroller(getContext());
        mCurrentColumn = 0;
        mPaint = new Paint();
        mPaint.setDither(false);
        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
        this.setChoiceMode(CHOICE_MODE_SINGLE);
        this.setFastScrollEnabled(enableFastScroll);
        beforeScrollFirstPosition = -1;
        beforeScrollY = -1;
        currentFirstItem = 0;

        if (android.os.Build.VERSION.SDK_INT >= 14) {
            if(mFirstVisibleItem != 0){
                setSelection(mFirstVisibleItem);
            }
        }

        //上拉加载更多
        super.setOnScrollListener(this);
        mFooterView = new EQCustomListViewFooterLoadMore(getContext());
    }

    public void setAdapter(ListAdapter adapter) {
        // make sure XListViewFooter is the last footer view, and only add once.
        if (mIsFooterReady == false) {
            mIsFooterReady = true;
            addFooterView(mFooterView);
        }
        super.setAdapter(adapter);
    }

    public void setPullLoadEnable(boolean enable) {
        mEnablePullLoad = enable;
        if (!mEnablePullLoad) {
            mFooterView.setState(EQCustomListViewFooterLoadMore.STATE_END);
        } else {
            mPullLoading = false;
            mFooterView.show();
            mFooterView.setState(EQCustomListViewFooterLoadMore.STATE_NORMAL);
        }
    }

    public void setStateEndHide(){
        mFooterView.setState(EQCustomListViewFooterLoadMore.STATE_END_HIDE);
    }

    public void showNoDataReminderView() {
        mFooterView.setState(EQCustomListViewFooterLoadMore.STATE_NO_DATA);
    }

    public void stopLoadMore() {
        if (mPullLoading == true) {
            mPullLoading = false;
            mFooterView.setState(EQCustomListViewFooterLoadMore.STATE_NORMAL);
        }
    }

    private void updateFooterHeight(float delta) {
        int height = mFooterView.getBottomMargin() + (int) delta;	//	height is not really the height of footer view, but the bottom margin of the footer view
        if (mEnablePullLoad && !mPullLoading) {
            if (height > PULL_LOAD_MORE_DELTA) { // height enough to invoke load
                // more.
                mFooterView.setState(EQCustomListViewFooterLoadMore.STATE_READY);
            } else {
                mFooterView.setState(EQCustomListViewFooterLoadMore.STATE_NORMAL);
            }
        }
        height = height>FOOTER_HEIGHT ? FOOTER_HEIGHT : height;
        mFooterView.setBottomMargin(height);
    }

    public void resetFooterHeight() {
        isResetFooterView = true;
        int bottomMargin = mFooterView.getBottomMargin();
        if (bottomMargin > 0) {
            mScrollBack = SCROLLBACK_FOOTER;
            mScroller.startScroll(mLastScrollX, bottomMargin, 0, -bottomMargin, SCROLL_DURATION);
            mFooterView.setBottomMargin(0);
            this.setSelection(this.getAdapter().getCount() - 1);
//			this.setSelection(this.getBottom());
            postInvalidate();
        }

        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {

            @Override
            public void run() {
                isResetFooterView = false;
            }
        }, 600);
    }

    private void startLoadMore() {
        mPullLoading = true;
        mFooterView.setState(EQCustomListViewFooterLoadMore.STATE_LOADING);
        if (mListViewListener != null) {
            mListViewListener.onLoadMore();
        }
    }

    public void setEQCustomListViewListener(EQCustomListViewListener l) {
        mListViewListener = l;
    }

    public Handler mUIHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case GOTO_SELECT:
                    if (mFirstVisibleItem != 0)
                    {
                        EQGirdListViewBase.this.setSelection(mFirstVisibleItem);
                        EQGirdListViewBase.this.postInvalidate();
                    }
                    break;
            }
        }
    };

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                         int totalItemCount) {
        if (scrollState == SCROLL_STATE_IDLE && !isResetFooterView) {
            mUIHandler.sendMessage(mUIHandler.obtainMessage(GOTO_SELECT));
        }
        mTotalItemCount = totalItemCount;
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (scrollState == SCROLL_STATE_IDLE) {
            if (mFirstVisibleItem != getFirstVisiblePosition()) {
                mFirstVisibleItem = this.getFirstVisiblePosition();
            }
        }
        this.scrollState = scrollState;
    }

    @Override
    /**
     * 鍒濆鍖栨彁绀烘鐨勯珮鍜屽
     */
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
    }

    /**
     * @return the listHeader
     */
    public EQGirdScrollableListItem getListHeader() {
        return listHeader;
    }

    /**
     * @param listHeader the listHeader to set
     */
    public void setListHeader(EQGirdScrollableListItem listHeader) {
        this.listHeader = listHeader;
    }

    /**
     * increase drawing speed by cache used
     */
    void enableChildrenCache() {
        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            final ViewGroup layout = (ViewGroup) getChildAt(i);
            layout.setAlwaysDrawnWithCacheEnabled(true);
        }
    }

    void clearChildrenCache() {
        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            final ViewGroup layout = (ViewGroup) getChildAt(i);
            layout.setAlwaysDrawnWithCacheEnabled(false);
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (mLocked) {
            return true;
        }
        if (mLastY == -1) {
            mLastY = ev.getRawY();
        }
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(ev);
        final int action = ev.getAction();
        final float x = ev.getX();
        final float y = ev.getY();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                mIsDragging = false;
                mLastMotionX = x;
                mLastMotionDownX = x;
                mLastMotionDownY = y;

                mLastY = ev.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                final int xDiff = (int) Math.abs(x - mLastMotionDownX);
                final int yDiff = (int) Math.abs(y - mLastMotionDownY);
                if(xDiff > mTouchSlop && xDiff > 2 * yDiff){
                    mIsDragging = true;
                }
                if (mIsDragging) {
                    if(x > mLastMotionX){
                        mDirection = DIRECTION_RIGHT;
                    }else{
                        mDirection = DIRECTION_LEFT;
                    }
                    // Scroll to follow the motion event
                    final int deltaX = (int) (mLastMotionX - x);
                    mLastMotionX = x;
                    if (deltaX < 0) {
                        if (getMoveItemScrollX() > 0)
                        {
                            itemScrollBy(Math.max(-getMoveItemScrollX(), deltaX), 0);
                        }
                    } else if (deltaX > 0) {
                        final int availableToScroll = getAvailableToScroll();
                        if (availableToScroll > 0)
                        {
                            itemScrollBy(Math.min(availableToScroll, deltaX), 0);
                        }
                    }
                }

                final float deltaY = ev.getRawY() - mLastY;
                mLastY = ev.getRawY();
//			int nMargin = mFooterView.getBottomMargin();
//			int nLastPosition = getLastVisiblePosition();
                if (getLastVisiblePosition() == mTotalItemCount - 1
                        //&& (mFooterView.getBottomMargin() > 0 || deltaY < 0)) {
                        && mFooterView.getBottomMargin() < FOOTER_HEIGHT && deltaY < 0) {
                    updateFooterHeight(-deltaY / OFFSET_RADIO_FOOTER);
                }
                break;
            case MotionEvent.ACTION_UP:
                isActionUp = true;
                if (mFooterView.getstate() == EQCustomListViewFooterLoadMore.STATE_NORMAL) {
                    resetFooterHeight();
                }
                mLastY = -1;
                if (getLastVisiblePosition() == mTotalItemCount - 1) {
                    // invoke load more.
                    if (mEnablePullLoad
                            && mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA
                            && isActionUp) {
                        startLoadMore();
                    }
                    resetFooterHeight();
                }

                itemScrollBy(0,0);
                if (mIsDragging) {
                    final VelocityTracker velocityTracker = mVelocityTracker;
                    velocityTracker.computeCurrentVelocity(1000);
                    int velocityX = (int) velocityTracker.getXVelocity();
                    if (Math.abs(velocityX) < SNAP_VELOCITY) {
                        snapToColumnDestination();
                    } else {
                        fling(-velocityX);
                    }
                    if (mVelocityTracker != null) {
                        mVelocityTracker.recycle();
                        mVelocityTracker = null;
                    }

                    mIsDragging = false;
                    ev.setAction(MotionEvent.ACTION_CANCEL);
                    super.onTouchEvent(ev);
                    return true;
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                mIsDragging = false;
                //  break;
            default:
                mLastY = -1;
                if (getLastVisiblePosition() == mTotalItemCount - 1) {
                    // invoke load more.
                    if (mEnablePullLoad
                            && mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA
                            && isActionUp) {
                        startLoadMore();
                    }
                    resetFooterHeight();
                }
                break;
        }

        if(!mIsDragging){
            super.onTouchEvent(ev);
        }
        return true;
    }

    @SuppressWarnings("unused")
    private void snapToColumn(int whichColumn) {
        enableChildrenCache();
        whichColumn = Math.max(0, Math.min(whichColumn, getScrollColumnCount() - 1));
        mNextColumn = whichColumn;
        int width = getColumnWidth();
        int newX = whichColumn * width;
        int delta = newX - getMoveItemScrollX();
        switch(mDirection){
            case DIRECTION_LEFT:
                newX = (whichColumn + 1) * width;
                delta = newX - getMoveItemScrollX() - getVisiableForScroll();
                break;
            case DIRECTION_RIGHT:
                delta = newX - getMoveItemScrollX();
                break;
        }
        mDirection = DIRECTION_NONE;
        mScroller.startScroll(getMoveItemScrollX(), 0, delta, 0, Math.abs(delta) * 2);
        postInvalidate();
    }

    private void snapToColumnDestination() {
    }

    /**
     * 鑾峰彇鍒楄〃item鍚戝乏婊戝姩鐨勮窛绂�
     * @return
     */
    public int getItemScrollX(){
        return mLastScrollX;
    }

    /**
     * 鍦╔鏂瑰悜涓婅繘琛岃繕鍘燂紝鏄剧ず绗竴鍒楁暟鎹�
     * @return
     */
    public boolean scrollXRestore(){
        int deltaX = getMoveItemScrollX();
        if(deltaX > 0){
            itemScrollBy(-deltaX, 0);
            return true;
        }
        return false;
    }

    public void snapToWindowDestination() {
        final int itemScrollX = getMoveItemScrollX();
        final int viewPort = getScrollableViewPort();
        final int scrollItemWidth = getScrollItemWidth();
        int toX = itemScrollX;
        if (itemScrollX > 0) {
            if (viewPort > scrollItemWidth) {
                toX = 0;
            } else {
                if (itemScrollX + viewPort > scrollItemWidth) {
                    if (scrollItemWidth > viewPort) {
                        toX = scrollItemWidth - viewPort;
                    }
                }
            }
        }
        enableChildrenCache();
        final int delta = toX - getMoveItemScrollX();
        mScroller.startScroll(getMoveItemScrollX(), 0, delta, 0, Math.abs(delta) * 2);
        postInvalidate();
    }

    public void itemScrollBy(int x, int y) {
        mLastScrollX = getMoveItemScrollX() + x;
        int count = this.getChildCount();
        for (int i = 0; i < count; i++) {
            View v = getChildAt(i);
            if (v instanceof EQGirdScrollableListItem)
            {
                EQGirdScrollableListItem item = (EQGirdScrollableListItem) v;
                View moveItem = item.getScrollableView();
                if (moveItem != null) {
                    moveItem.scrollTo(mLastScrollX, moveItem.getScrollY());
                }
            }
        }
        // header
        if (listHeader != null) {
            View v = listHeader.getScrollableView();
            v.scrollTo(mLastScrollX, v.getScrollY());
        }
        postInvalidate();
    }

    @SuppressLint("Override")
    public void fling(int velocityX) {
        enableChildrenCache();
        mScroller.fling(getMoveItemScrollX(), 0, velocityX, 0, 0, getTotalToScroll(), 0, 0);
        // final boolean movingRight = velocityX > 0;
        postInvalidate();
    }

    /**
     * 婊氬姩鍒嗕袱閮ㄥ垎锛屼竴閮ㄥ垎鏄痟ead鐨勬粴鍔紝鍙︿竴閮ㄥ垎鏄痟ead涓嬮潰鍐呭鐨勬粴鍔�
     */
    public void computeItemsScroll(){
        if (mScroller == null)
            return;
        int mScrollX = mScroller.getCurrX();
        int mScrollY = mScroller.getCurrY();
        // this.scrollTo(mScrollX, mScrollY);
        //婊氬姩鍒嗕袱閮ㄥ垎锛屼竴閮ㄥ垎鏄痟ead鐨勬粴鍔紝鍙︿竴閮ㄥ垎鏄痟ead涓嬮潰鍐呭鐨勬粴鍔�
        //1. 杩欎竴閮ㄥ垎鏄厛鎵惧埌鍐呭鐨剉iew锛岀劧鍚庤view婊氬姩
        int count = this.getChildCount();
        for (int i = 0; i < count; i++) {
            View v = getChildAt(i);
            if (v instanceof EQGirdScrollableListItem) {
                View moveItem = ((EQGirdScrollableListItem) v).getScrollableView();
                if (v != null) {
                    moveItem.scrollTo(mScrollX, mScrollY);
                }
            }
        }
        // 2. 杩欎竴閮ㄥ垎鏄痟ead鐨勬粴鍔�
        if (listHeader != null) {
            View v = listHeader.getScrollableView();
            v.scrollTo(mScrollX, v.getScrollY());
        }
        mLastScrollX = mScrollX;
        postInvalidate();
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mScroller == null)
            return;

        if (mScroller.computeScrollOffset()) {
            if (mScrollBack != SCROLLBACK_HEADER) {
                mFooterView.setBottomMargin(mScroller.getCurrY());	//	update Bottom Margin of footer view in real time
                postInvalidate();
                //invokeOnScrolling();
            }
            computeItemsScroll();
        } else {
            if (!mIsDragging){
                snapToColumnDestination();
            }
            if (mNextColumn != INVALID_COLUMN) {
                int newScreen = Math.max(0, Math.min(mNextColumn, getChildCount() - 1));
                if (mCurrentColumn != newScreen) {
                    mCurrentColumn = newScreen;
                    // viewChanged(mCurrentScreen);
                    mNextColumn = INVALID_COLUMN;
                    clearChildrenCache();
                }
            }
        }
    }

    private int getVisiableForScroll(){
        int scroll = 0;
        EQGirdScrollableListItem moveItem = findEQGirdScrollableListItem();

        if (moveItem != null) {
            scroll = moveItem.getScrollableView().getWidth();;
        }
        // getChildAt(getChildCount() - 1).getRight() - getScrollX() - getWidth();
        return scroll;
    }

//    private void checkArrow(){
//        if(listHeader instanceof DragableListViewItemExt){
//            DragableListViewItemExt item = (DragableListViewItemExt)listHeader;
//            if(getMoveItemScrollX() == 0){
//                item.setLeftArrowVisiable(false);
//            }else{
//                item.setLeftArrowVisiable(true);
//            }
//            if(getMoveItemScrollX() == item.totalToScroll()){
//                item.setRightArrowVisiable(false);
//            }else{
//                item.setRightArrowVisiable(true);
//            }
//        }
//    }

    private int getAvailableToScroll() {
        int scroll = 0;
        EQGirdScrollableListItem moveItem = findEQGirdScrollableListItem();
        if (moveItem != null) {
            scroll = moveItem.availableToScroll();
        }
        // getChildAt(getChildCount() - 1).getRight() - getScrollX() - getWidth();
        return scroll;
    }

    private int getTotalToScroll() {
        int totalToScroll = 0;
        EQGirdScrollableListItem item = findEQGirdScrollableListItem();
        if (item != null && item.getScrollableView() != null) {
            totalToScroll = item.totalToScroll();
        }
        return totalToScroll;
    }

    private int getScrollColumnCount() {
        int count = 0;
        EQGirdScrollableListItem item = findEQGirdScrollableListItem();
        if (item != null && item.getScrollableView() != null) {
            count = item.getScrollColumnCount();
        }
        return count;
    }

    private int getColumnWidth() {
        int width = 0;
        EQGirdScrollableListItem item = findEQGirdScrollableListItem();
        if (item != null && item.getScrollableView() != null) {
            width = item.getColumnWidth();
        }
        return width;
    }

    @SuppressWarnings("unused")
    private int getDestX(int whichColumn) {
        int width = 0;
        EQGirdScrollableListItem item = findEQGirdScrollableListItem();
        if (item != null && item.getScrollableView() != null) {
            width = item.getColumnWidth();
        }
        return width;
    }

    private int getScrollableViewPort() {
        int scrollableViewPort = 0;
        EQGirdScrollableListItem item = findEQGirdScrollableListItem();
        if (item != null && item.getScrollableView() != null) {
            scrollableViewPort = getWidth() - item.getScrollableView().getLeft();
        }
        return scrollableViewPort;
    }

    private int getMoveItemScrollX() {
        int scrollX = 0;
        EQGirdScrollableListItem item = findEQGirdScrollableListItem();
        if (item != null && item.getScrollableView() != null) {
            scrollX = item.getScrollableView().getScrollX();
        }
        return scrollX;
    }

    private int getScrollItemWidth() {
        int width = 0;
        EQGirdScrollableListItem item = findEQGirdScrollableListItem();
        if (item != null && item.getScrollableView() != null) {
            width = (item.getColumnCount() - item.getFixCount()) * item.getColumnWidth();
        }
        return width;
    }

    private EQGirdScrollableListItem findEQGirdScrollableListItem() {
        EQGirdScrollableListItem scrollItem = null;
        int count = this.getChildCount();
        for (int i = 0; i < count; i++) {
            View v = getChildAt(i);
            if (v instanceof EQGirdScrollableListItem) {
                scrollItem = ((EQGirdScrollableListItem) v);
                break;
            }
        }
        return scrollItem;
    }

    @SuppressWarnings("unused")
    private boolean isCanScrollAble(){
        EQGirdScrollableListItem item = findEQGirdScrollableListItem();
        if (item != null && item.getScrollableView() != null) {
            return item.isCanScrollAble();
        }
        return true;
    }

    public static interface EQGirdScrollableListItem {
        public int getColumnWidth();
        public int getColumnCount();
        public int getFixCount();
        public int getScrollColumnCount();
        public int availableToScroll();
        public int totalToScroll();
        public View getScrollableView();
        public boolean isCanScrollAble();
    }

    @Override
    public boolean onDown(MotionEvent arg0) {
        return false;
    }

    @Override
    public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2,
                           float arg3) {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent arg0) {
    }

    @Override
    public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2,
                            float arg3) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent arg0) {
    }

    @Override
    public boolean onSingleTapUp(MotionEvent arg0) {
        return false;
    }



    @Override
    protected void handleDataChanged() {
        super.handleDataChanged();
        if (null != dataChangedListener)
        dataChangedListener.onSuccess();
    }

    public void setDataChangedListener(DataChangedListener dataChangedListener) {
        this.dataChangedListener = dataChangedListener;
    }

    public interface DataChangedListener{
        public void onSuccess();
    }
}
